package com.zjw.endpoint;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zjw.domain.dto.WebSocketMessageDto;
import com.zjw.domain.entity.GroupMessage;
import com.zjw.domain.entity.User;
import com.zjw.domain.vo.GroupMessageVo;
import com.zjw.domain.vo.OnlineUserVo;
import com.zjw.domain.vo.WebSocketMessageVo;
import com.zjw.service.GroupMessageService;
import com.zjw.service.UserService;
import com.zjw.system.WebsocketMessageEnum;
import com.zjw.utils.BeanCopyUtil;
import com.zjw.utils.JWTUtil;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
@ServerEndpoint("/square/{token}")
public class SquareEndpoint implements InitializingBean {

    private static final Map<Long, Session> onlineUserMap = new HashMap<>();

    @Autowired
    private UserService userService;

    @Autowired
    private GroupMessageService groupMessageService;

    private static UserService staticUserService;

    private static GroupMessageService staticGroupMessageService;

    @Override
    public void afterPropertiesSet() throws Exception {
        staticUserService = userService;
        staticGroupMessageService = groupMessageService;
    }

    @OnOpen
    public void onOpen(Session session, @PathParam("token") String token) {
        //    解析token查看是否有效；无效则直接断开
        if (!JWTUtil.validateJWT(token)) {
            try {
                session.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }
        Long id = JWTUtil.getJWTId(token);
        //    有效则将session加入map中
        session.getUserProperties().put("id", id);
        onlineUserMap.put(id, session);
        //    并广播
        broadcastAll(getOnlineUserList(), WebsocketMessageEnum.GROUP_ONLINE_USER_LIST);
    }

    /**
     * message是一个json串对应类型是WebSocketMessageDto： type、message两个字段
     *
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        WebSocketMessageDto msg = JSON.parseObject(message, WebSocketMessageDto.class);

        if(StrUtil.isBlank(msg.getMessage()))
            return;
        msg.setMessage(msg.getMessage().trim());

        //System.out.println("===========================");
        //System.out.println(session.getUserProperties().get("id") + "发信信息:");
        //System.out.println("type:" + msg.getType());
        //System.out.println(msg.getMessage());
        //System.out.println("===========================");

        //    将新消息放进数据库
        Long id = (Long)session.getUserProperties().get("id");
        GroupMessage newMsg = new GroupMessage();
        newMsg.setCreateBy(id);
        newMsg.setUserId(id);
        newMsg.setType(msg.getType());
        newMsg.setContent(msg.getMessage());
        newMsg.setCreateTime(new Date());
        staticGroupMessageService.save(newMsg);

        //    将新消息广播给所有session
        GroupMessageVo groupMessage = BeanCopyUtil.copyBean(newMsg, GroupMessageVo.class);
        groupMessage.setAvatar(staticUserService.getUserAvatarById(id));
        groupMessage.setUsername(staticUserService.getUserNameById(id));

        broadcastAll(groupMessage, WebsocketMessageEnum.GROUP_NEW_MESSAGE);
    }

    @OnClose
    public void onClose(Session session) {
        if (session.getUserProperties().get("id") == null || !onlineUserMap.containsKey(session.getUserProperties().get("id"))) {
            //    没有直接退出
            return;
        }
        onlineUserMap.remove(session.getUserProperties().get("id"));
        broadcastAll(getOnlineUserList(), WebsocketMessageEnum.GROUP_ONLINE_USER_LIST);
    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    private static Object getOnlineUserList() {
        ArrayList<OnlineUserVo> res = new ArrayList<>();
        //   查询用户放进Vo并转为字符串返回
        onlineUserMap.entrySet().stream().forEach(s -> {
            Long id = (Long) s.getValue().getUserProperties().get("id");
            //    查询用户放入vo中
            OnlineUserVo temp = BeanCopyUtil.copyBean(staticUserService.getById(id), OnlineUserVo.class);
            res.add(temp);
        });

        return res;
    }

    private static void broadcastAll(Object message, WebsocketMessageEnum messageEnum) {
        //    向所有的在线用户广播
        onlineUserMap.entrySet().stream().forEach(s -> {
            Session temp = s.getValue();
            try {
                temp.getBasicRemote()
                        .sendText(JSON.toJSONString(
                                new WebSocketMessageVo(messageEnum.getCode(), message)
                        ));
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

    }


}
